from twisted.internet import reactor, protocol
from twisted.protocols import basic
import time
import cPickle
import common.defines as defines
from passlib.handlers.django import django_pbkdf2_sha256 as handler
from common.message import Message
from common.deck import *
from common.card import *
from common.hand import *
from common.dealer import Dealer
from common.player import Player
import uuid
import MySQLdb as mdb

def t():
    return "[{0}]".format(time.strftime("%H:%M:%S"))

class CardGame(object):
    
    def __init__(self, comm):
        self.deck = Deck(6)
        self.deck.shuffle()
        
        self.comm = comm #EchoProtocol
        
        self.dealer = Dealer()
        self.players = []
        self.wait = [];
          
        
class EchoProtocol(basic.LineReceiver):
    name = "Unnamed"
    
    def __init__(self):
        self.cardgame = CardGame(self)
    
    def selfSend(self, msg):
        msg = Message(payload=msg)
        self.sendLine(cPickle.dumps(msg))
        
    def connectionMade(self):
        
        self.count = 0
        self.factory.clients.append(self)
        tmp = Player(id=uuid.uuid1(), name='')
        self.cardgame.players.append(Player(''))
        msg = Message(msg_type=defines.PLAYER_INIT, player_id=tmp.id)
        self.sendLine(cPickle.dumps(msg))
        print t() + "+ Connection from : " + self.transport.getPeer().host
    
    def connectionLost(self, reason):
        self.sendMsg("- {0} left.".format(self.name))
        print "{0} - Connection lost: {1}".format(t(), self.name)
        self.factory.clients.remove(self)
        
    def lineReceived(self, msg):
        msg = cPickle.loads(msg)
        
        
        #ACTION
        if msg.msg_type == defines.MSG_ACTION:
            action = msg.payload
            player_id = msg.player_id
            #DEAL CARD
            if action == defines.ACTION_HITME:
                card = self.cardgame.deck.deal_card()
                msg = Message(defines.OBJ_CARD, player_id, card)
                self.sendLine(cPickle.dumps(msg))
                return
                
        elif msg.msg_type == defines.MSG_CHAT_BROADCAST:
            line = msg.payload
            if line == 'quit':
                msg = Message(payload="Goodbye.")
                self.sendLine(cPickle.dumps(msg))
                self.transport.loseConnection()
                return
            elif line == "userlist":
                self.chatters()
                return
            if not self.count:
                self.username(line)
            else:
                self.sendMsg("{0}: {1}".format(self.name, line))
        
        elif msg.msg_type == defines.AUTH_INIT:
            con = None
            credentials = msg.payload
            player_id = msg.player_id
            authorized = False
            try:
                con = mdb.connect(host='127.0.0.1', user='netjack', passwd='netjack', db='netjack', port=3306)
                cur = con.cursor(mdb.cursors.DictCursor)
                
                cur.execute("SELECT * FROM AUTH_USER WHERE USERNAME=%s", (credentials.username))
                row = cur.fetchone()
                #GET iterations, salt, hash
                db_hash = row['password']
                
                if db_hash != None:
                    authenticated = handler.verify(credentials.password_ascii, db_hash)
                    if authenticated:
                        user_id = row['id']
                        cur.execute("SELECT balance from bank where user_id=%s", (user_id))
                        row = cur.fetchone()
                        hand = [self.cardgame.deck.deal_card(), self.cardgame.deck.deal_card()]
                        msg = Message(defines.AUTH_USER_AUTHENTICATED, player_id, payload={'name': credentials.username, 'balance': row['balance'], 'hand': hand})        
                        authorized = True
                
                if not authorized:
                    msg = Message(defines.AUTH_USER_NOT_AUTHENTICATED, player_id, payload="Username or password was invalid.")
                
                self.sendLine(cPickle.dumps(msg))
                    
                
            except Exception, ex:
                print ex
          
    def username(self, line):
        for x in self.factory.clients:
            if x.name == line:
                self.selfSend("This username is taken; please choose another")
                return
            
        self.name = line
        self.chatters()
        
        self.sendLine("Welcome to NetJack")
        self.sendLine("")
        
        self.count += 1
        
        self.sendMsg("+ {0} joined.".format(self.name))
        print '{0}~ {1} is now known as {2}'.format(t(), self.transport.getPeer().host, self.name)
    
    def chatters(self):
        x = len(self.factory.clients) - 1
        s = 'is' if x == 1 else 'are'
        p = 'person' if x == 1 else 'people'
        
        self.selfSend("There {0} {1} {2} connected".format(s, x, p))
        
        for client in self.factory.clients:
            if client is not self:
                self.sendLine(client.name)
        self.selfSend("")

    def sendMsg(self, message):
        for client in self.factory.clients:
            msg = Message(payload=t() + message)
            client.sendLine(cPickle.dumps(msg))
            msg = Message(payload="")
            client.sendLine(cPickle.dumps(msg))
            
class EchoServerFactory(protocol.ServerFactory):
    protocol = EchoProtocol
    clients = []
    
    
if __name__ == '__main__':
    reactor.listenTCP(5001, EchoServerFactory())
    reactor.run()
#    cardGame = CardGame()
    
#import socket               # Import socket module
#import cPickle
#from common import *
#s = socket.socket()         # Create a socket object
#host = socket.gethostname() # Get local machine name
#port = 12345                # Reserve a port for your service.
#s.bind((host, port))        # Bind to the port
#
#s.listen(5)                 # Now wait for client connection.
#while True:
#    c, addr = s.accept()     # Establish connection with client.
#    print 'Got connection from', addr
#    
#    #Create card object Ace of Spades
#    mycard = card.Card(0,3)
#    
#    #serialize the data
#    data = cPickle.dumps(mycard)
#    
#    #send the data
#    c.send(data)
#    c.close()                # Close the connection